/**
 * Created by coder on 2018/1/15.
 */
import {ACTION_ADD_MEMORY,
	ACTION_UPDATE_ALL_CELLS,
	ACTION_UPDATE_CELLS,
	ACTION_SET_CUR_CELL,
	ACTION_UNDO,
	ACTION_REDO} from '../store/action'
import {initializeArrayWithValues} from './array'
import updateErrorMap from './updateErrorMap'

export const addMemory = () => {
	return (dispatch,getState) => {
		const {cells} = getState();
		const cellsData = cells.map((cell) => {
			return cell.isMark ? cell.numMark : cell.data;
		});

		dispatch({
			type:ACTION_ADD_MEMORY,
			payload:{
				cells:cellsData
			}
		});
	}
};

const isCellTheSame = (orgItem,newItem) => {
	if(orgItem.isStatic)
		return true;

	if(orgItem.isMark !== newItem.isMark)
		return false;

	if(orgItem.isMark){
		for(let i=0;i<9;i++){
			if(orgItem.numMark[i] !== newItem.numMark[i])
				return false;
		}
		return true;
	} else {
		return orgItem.data === newItem.data;
	}
};

const isNumMarkTheSame = (left,right) => {
	for(let i=0;i<9;i++){
		if(left[i] !== right[i])
			return false;
	}
	return true;
};

export const redoAction = () => {
	return (dispatch,getState) => {
		const {cells,curCell} = getState();
		const orgItem = cells[curCell.y*9+curCell.x];
		if(!isCellTheSame(orgItem,curCell)){
			dispatch({
				type:ACTION_SET_CUR_CELL,
				payload:{
					cell:Object.assign({},orgItem),
				},
			});
		}
		
		dispatch({
			type:ACTION_REDO,
		});

		let changeCell = null;
		const {memory} = getState();
		const {cur} = memory;
		let newCells = cells.slice();
		for(let i=0;i<81;i++){
			const memItem = cur[i];
			const cellItem = newCells[i];
			if(typeof memItem === 'number'){
				if(!(cellItem.isMark === false && memItem === cellItem.data)){
					newCells[i] = Object.assign({},cellItem,{data:memItem,isMark:false,numMark:initializeArrayWithValues(9,false)});
					changeCell = newCells[i];
					break;
				}
			} else {
				if(!(cellItem.isMark === true && isNumMarkTheSame(memItem,cellItem.numMark))){
					newCells[i] = Object.assign({},cellItem,{data:0,isMark:true,numMark:memItem});
					changeCell = newCells[i];
					break;
				}
			}
		}

		dispatch({
			type:ACTION_UPDATE_ALL_CELLS,
			payload:newCells,
		});

		dispatch({
			type:ACTION_SET_CUR_CELL,
			payload:{
				cell:Object.assign({},changeCell),
			},
		});

		if(changeCell){
			updateErrorMap(changeCell)(dispatch,getState);
		}

	}
};

export const undoAction = () => {
	return (dispatch,getState) => {
		const {cells,curCell} = getState();
		const orgItem = cells[curCell.y*9+curCell.x];
		if(!isCellTheSame(orgItem,curCell)){
			dispatch({
				type:ACTION_SET_CUR_CELL,
				payload:{
					cell:Object.assign({},orgItem),
				},
			});
		}

		dispatch({
			type:ACTION_UNDO,
		});

		let changeCell = null;
		const {memory} = getState();
		const {cur} = memory;
		let newCells = cells.slice();
		for(let i=0;i<81;i++){
			const memItem = cur[i];
			const cellItem = newCells[i];
			if(typeof memItem === 'number'){
				if(!(cellItem.isMark === false && memItem === cellItem.data)){
					newCells[i] = Object.assign({},cellItem,{data:memItem,isMark:false,numMark:initializeArrayWithValues(9,false)});
					changeCell = newCells[i];
					break;
				}
			} else {
				if(!(cellItem.isMark === true && isNumMarkTheSame(memItem,cellItem.numMark))){
					newCells[i] = Object.assign({},cellItem,{data:0,isMark:true,numMark:memItem});
					changeCell = newCells[i];
					break;
				}
			}
		}

		dispatch({
			type:ACTION_UPDATE_ALL_CELLS,
			payload:newCells,
		});

		dispatch({
			type:ACTION_SET_CUR_CELL,
			payload:{
				cell:Object.assign({},changeCell),
			},
		});

		if(changeCell){
			updateErrorMap(changeCell)(dispatch,getState);
		}
	}
};